Very Large Numbers - VLN This Object Class allows the user to compute to very high precision. The unique feature of this Object class is that numbers are supported up to 1000 decimal digits or more, limited only by available memory. While only integer data is supported, scaled arithmetic allows numbers to be used as small as 1 x 10 ^ -1000 or smaller. Several basic operations are provided such as add, subtract, multiply and divide. Further useful operations include 2^n, 10^n, nth-power and nth-Root. Write Hexadecimal and Write Decimal procedures are included. Object definition: )))))))))))))))))))))))))))))))))))))))))) )) )) )) pWordArray = ^tWordArray )) )) tWordArray = object )) )) array[1..vlsize] of word; )) )) end; )) )) )) )) pVryLrgNo =^tVryLrgNo; )) )) tVryLrgNo = object )) )) count : integer; )) )) max : integer; )) )) sign : integer; )) )) tVLN : tWordArray; )) )) )) )) procedures and functions. )) )) end; )) )) )) )))))))))))))))))))))))))))))))))))))))))) One problem in defining this data type, that can contain more than a thousand bytes, is that there is no best size for 'vlsize' the maximum allowed size. Some applications will need a few numbers of immense size while others will need many but not so big. The user, if he does nothing special may use the default size of 1000 words (which allows 5300 decimal digits) for all variables in his program. A way is illustrated to use less memory assuming he knows how large the numbers will actually be. This method uses GETMEM( name, size) In the process of initializing a VLN variable, the programmer also specifies 'MAX' the maximum size expected and this is tested in all arithmetic procedures. The main program is responsible for OpenTempRegs at the start and CloseTempRegs at the end as well as disposing of any dynamic variables that are created. This is to allow the user to specify maximum size of the VLN before the arithmetic working registers are initialized. {------------------------------------------------------------} VLN Fields count - the number of tVLN words used, tVLN[count] is expected to be non-zero, while higher words are - undefined max - The number of tVLN words for which space is assigned Writing to a higher word may cause a crash. sign - " +1" signifies positive " -1" signifies negative tVLN - A set of "1 . . max" words representing a positive integer. tVLN[1] is least significant and tVLN[count] is most significant. If tVLN[count] is zero then the same VLN number can be represented by the same data set except with count= count-1. This is a situation that is awkward but all algorithms included here should accept the redundant representations. ------------------------------------------------------------- Description of procedures and functions constructor Init( cnt, maxC, sgn : integer; pnew :pWordArray); The normal place to set "max" := maxC. Most arithmetic routines check the current "count" against "max" This constructor calls Set Value (below) procedure SetVal( cnt, sgn : integer; pnew :pWordArray); Assumes that max is previously set. Count is set to cnt Sign is set to sgn tVLN is set to contents of pnew procedure SetSmall(n:integer); { set immediate to 16 bits, signed } same as SetVal, except operand limited to +/- integer. Count is set to 1 Sign" set to sign of n tVLN[1] is set to absv(n) procedure Clear( n : integer); Count is set to 0 Sign is set to 1 max" and "tVLN" unchanged procedure Copy( other : pVryLrgNo ); { copy other into self } Previous values are discarded except Max" is retained. Sign, Count and tVLN terms are taken from "other" if other.count > self.max then an error is called. procedure WriteHex; Write to screen, Most significant data first procedure WriteDecimal ( mode : integer); Write to screen in decimal format. In mode=0 Most significant data is first in mode=1 least significant data is first in mode=2 only one or two most significant terms are shown procedure AddBy(other : pVryLrgNo); The present value is added to "other". Count & Sign are set to calculated values. tVLN[i] will contain new calculated data. procedure AddN(n:integer); Same as Addby except that the operand is a provided integer. procedure SubBy(other : pVryLrgNo); The value "other" is subtracted from the present value. Count & Sign are set to calculated values. tVLN[i] will contain new calculated data. procedure SubN(n:integer); Same as Subby except that the operand is a provided integer. procedure TwosComplAbs( cnt : integer ); Sign and Count are unchanged. Each term of tVLN from 1 to count is changed with terms converted by the equation --- t := 65536-t up to and including the first non-zero term. Subsequent terms are converted by the equation --- t := 65535-t up to and including tVLN[count] procedure MulBy(other : pVryLrgNo); The present value is multiplied by "other". Count & Sign are set to calculated values. tVLN[i] will contain new calculated data. procedure MultN(n:integer); Same as Mulby except that the operand is a provided integer. procedure DivBy( dvsr, remnd : pVryLrgNo); The present value is divided by "other". Count & Sign are set to calculated values. tVLN[i] will contain new calculated data. procedure DivN(n:integer); Same as Addby except that the operand is a provided integer. procedure TwoNth(n:integer ); Discards present count, sign, and tVLN words and sets Sign is set to 1, Count is set to (n div 16) + 1 all tVLN terms < count-1 = 0 tVLN[count] = 2^(n mod 16) procedure TenNth(n:integer ); Discards present count, sign, and tVLN words Sign is set to 1 If n=1 then count is set to 1 and tVLN[1] is set to 10 If n>1 then tVLN becomes integer 10 is multiplied by itself (n-1) times procedure NthRoot(n:integer ); The present value is used to calculate it's Nth root Sign is set to 1; Count and tVLN are calculated In general the number of significant bits is decreased and is inversely proportional to n. procedure NthPower(n:integer ); The present value is used to calculate it's Nth power. Sign is set to 1; Count and tVLN are calculated In general the number of significant bits is increased and is directly proportional to n. function FindnoBinDig : integer; { how many binary digits } Counts the number of significant digits, binary with each term less than count = 16 and using the actual number of bits in tVLN[count] procedure BigSHL(cnt : integer); {shift left by words } The entire VLN is multiplied by 2^16. Count is incremented and tVln[1] becomes 0. procedure MultiSHL(sf_cnt : integer); {shift left by bits } Will shift the entire VLN by 1 to 15 bits. If tVLN[count] overflows, then count is incrementd and the overflow bits are placed in the new tVLN[count]. procedure Shr1Bit; {shift right one bit} The entire VLN is divided by 2. If tVLN[count] was initially = 1 then count is decremented. procedure ShL1Bit; {shift left one bit} The entire VLN is multiplied by 2. If the word tVLN[count] overflows then count is incremented and the new highest term is set to 1. function FindDivShift(other : pVryLrgNo) : integer; Finds required shift in preparation for dividing. This allows the divisor to be initially positioned so that it is not larger than the dividend. Ideally the divisor would be positioned so that it at least half as large as the dividend. However this routine only looks at the most significant terms of dividend and divisor so it may start smaller than optimum. procedure GetRandom(binCnt : integer); Returns a random number with bincnt binary bits. The tVLN terms are defined using pascal's random function. In addition the top term is masked to give the number of significant bits in that word as calculated by "bincnt" mod 16. procedure Recount; Tests each tVLN term starting at "count" and working down until a non-zero term is found. Count is decremented to point to that non-zero word or is set to zero if no non-zero terms are found. Other routines for manipulating the Class tVryLrgNo; function MaxOfW (a,b : word) : word; Returns a or b whichever is larger; function IsGrEqAbs (n1, n2 : pVryLrgNo): boolean; { Returns true if variable pointed to by n1 is larger than variable pointed to by n2, without considering sign, (treating both as though they were positive numbers) function IsEqAbs (n1, n2 : pVryLrgNo): boolean; Returns true if variable pointed to by n1 is equal to variable pointed to by n2, without considering sign, (treating both as though they were positive numbers) procedure HexWord ( w : word; var pS : pchar4); Returns a 4-character array; pchar4 is defined as --- array[0..4]of char; procedure SetWkSize (n:integer); Sets the size that internal arithmetic registers will be initialized to when calling ' OpenTempRegs ' function GetWkSize : integer; Retreives the current value of wksize procedure CloseTempRegs ; Initializes several temporary arithmetic registers using GetMem and with size = 'wksize' procedure OpenTempRegs ; Disploses of several temporary arithmetic registers using FreeMem and with size = 'wksize' procedure CallError (s:String); Prints the string 's' ---------------------------------------------------------------------------------- Included files VLNCLS.PAS defines the Class - tVryLrgNo FACTRL calculates factorials FIBNACII calculates the Fibonacii series MATRIX2 Creates an array of reciprocals PI_4_96 calculates PI SQROOT calculates square roots to variable precision ROOTS calculates specified root to 36 decimal digits ---------------------------------------------------------------------------------- This program is given to public without restriction ----------------------------------------------------------------------------------